<?php
/*********************************************************************************
 * Copyright (C) 2011-2013 X2Engine Inc. All Rights Reserved.
 *
 * X2Engine Inc.
 * P.O. Box 66752
 * Scotts Valley, California 95067 USA
 *
 * Company website: http://www.x2engine.com
 * Community and support website: http://www.x2community.com
 *
 * X2Engine Inc. grants you a perpetual, non-exclusive, non-transferable license
 * to install and use this Software for your internal business purposes.
 * You shall not modify, distribute, license or sublicense the Software.
 * Title, ownership, and all intellectual property rights in the Software belong
 * exclusively to X2Engine.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT.
 ********************************************************************************/

/* @edition:pro */

/*
 * Records a contact's visit to a website.
 *
 * Used by embedding an iframe with weblistener.php or index.php/api/webListener
 * on the website.
 * Tracks using a cookie set by filling out a web capture form.
 * Looks up the contact by trackingKey, and creates a "webactivity" type action.
 */
class WebListenerAction extends CAction {

	public function run() {
		self::track();
	}

	public static function track() {
		if(!Yii::app()->params->admin->enableWebTracker)
			return;

		$keys = array();

		// figure out what kind of key has been provided
		if(isset($_GET['x2_key']) && ctype_alnum($_GET['x2_key']))
			$keys['linkKey'] = $_GET['x2_key'];
		if(isset($_COOKIE['x2_key']) && ctype_alnum($_COOKIE['x2_key']))
			$keys['cookieKey'] = $_COOKIE['x2_key'];

		$url = isset($_GET['url'])? $_GET['url'] : '';

		$contact = false;

		// look up the link key, then the cookie key
		foreach($keys as $keyName => $key) {

			$contact = self::trackCampaignClick($key,$url);		// see if this key is a campaign key

			if($contact === true)	// means there's no contact record (newsletter type campaign)
				return;				// no further tracking to be done, time to go home

			if($contact === false)							// no campaign key found,
				$contact = self::trackGeneric($key,$url);	// see if the key is a generic tracking key

			if($contact instanceof Contacts) {	// we found the contact!

				$contact->lastActivity = time();	// update lastActivity
				if(empty($contact->trackingKey))
					$contact->trackingKey = Contacts::getNewTrackingKey();	// make sure contact has a generic tracking key
				$contact->update(array('lastActivity','trackingKey'));

				self::setKey($contact->trackingKey);		// set tracking cookie in this contact's browser
				break;
			}
		}
	}


	/**
	 * Looks up the contact with the generic tracking key provided
	 * and creates actions/events/notifications
	 *
	 * @param string $key the generic tracking key to find the contact by
	 * @param string $url the referring URL
	 * @return mixed the contact if it is found, FALSE otherwise
	 */
	public static function trackGeneric($key,$url) {
		$contact = CActiveRecord::model('Contacts')->findByAttributes(array('trackingKey'=>$key));
		if($contact === null)
			return false;

		$now = time();

		// let's see if there's already a recent record about this
		$latest = Yii::app()->db->createCommand()
			->select('MAX(completeDate)')
			->from('x2_actions')
			->where('associationId=:id AND associationType="contacts" AND type="webactivity"',array(':id'=>$contact->id))
			->queryScalar();

		if($latest === null || $latest < $now - Yii::app()->params->admin->webTrackerCooldown) {	// ignore if it's been < 1 min since the last visit

			// run automation
			X2Flow::trigger('WebActivityTrigger',array(
				'model'=>$contact,
				'url'=>$url,
			));

			$action = new Actions('webTracker');
			$action->associationType = 'contacts';
			$action->associationId = $contact->id;
			$action->type = 'webactivity';
			$action->assignedTo = $contact->assignedTo;
			$action->visibility = '1';
			$action->associationName = $contact->name;
			$action->actionDescription = $url;
			$action->createDate = $now;
			$action->lastUpdated = $now;
			$action->completeDate = $now;
			$action->complete= 'Yes';
			$action->updatedBy = 'admin';
			$action->save();

			$event = new Events;
			$event->level=1;
			$event->user = $contact->assignedTo;
			$event->type = "web_activity";
			$event->associationType = 'Contacts';
			$event->associationId = $contact->id;
			$event->save();

			// create a notification if the record is assigned to someone
			if($contact->assignedTo != 'Anyone' && $contact->assignedTo != '') {
				$notif = new Notification;
				$notif->user = $contact->assignedTo;
				$notif->createdBy = 'API';
				$notif->createDate = time();
				$notif->type = 'webactivity';
				$notif->modelType = 'Contacts';
				$notif->modelId = $contact->id;
				$notif->save();
			}
		}
		return $contact;
	}

	/**
	 * Looks up the campaign list item with the provided unique ID, updates
	 * the campaign and sometimes creates actions, events and notifications
	 *
	 * @param string $uniqueId The unique id of the recipient
	 * @param string $url the referring URL
	 * @return mixed the contact model, if found, TRUE if uniqueId was found
	 * but there was no contact record (newsletter type campaign), or FALSE
	 * if uniqueId was not found in campaigns
	 */
	public static function trackCampaignClick($uniqueId,$url) {
		
		$item = CActiveRecord::model('X2ListItem')->with('contact','list')->findByAttributes(array('uniqueId'=>$uniqueId));
		if(!isset($item))
			return false;

		$campaign = CActiveRecord::model('Campaign')->findByAttributes(array('listId'=>$item->listId));
		if(!isset($item->list->campaign)) // Nonexistent campaign
			return false;

		$item->markClicked($url);

		$action = new Actions;
		$action->type = 'email_clicked';
		$action->completeDate = time();
		$action->complete = 'Yes';
		$action->updatedBy = 'API';

		if($item->contact) { // Contact is present and in the email campaign

			$action->associationType = 'contacts';
			$action->associationId = $item->contact->id;
			$action->associationName = $item->contact->name;
			$action->visibility = $item->contact->visibility;
			$action->assignedTo = $item->contact->assignedTo;

			$action->actionDescription = Yii::t('marketing','Campaign') .': '. $campaign->name."\n\n"
				.Yii::t('marketing','Contact has clicked a link') .":\n". urldecode($url);

			// create event
			$event = new Events;
			$event->level = 3;
			$event->associationId = $action->associationId;
			$event->associationType = 'Contacts';
			$event->type = 'email_clicked';
			$event->save();

			// create notification
			if($action->assignedTo !== '' && $action->assignedTo !== 'Anyone') {
				$notif = new Notification;
				$notif->type = 'email_clicked';
				$notif->user = $action->assignedTo;
				$notif->modelType = 'Contacts';
				$notif->modelId = $action->associationId;
				$notif->createDate = time();
				$notif->value = $campaign->getLink();
				$notif->save();
			}

			X2Flow::trigger('CampaignWebActivityTrigger',array(
				'model'=>$item->contact,
				'campaign'=>$campaign,
				'url'=>$url,
			));

		} else { // Contact not set; was deleted or part of a newsletter-type campaign
			$action->actionDescription = Yii::t('marketing','Campaign') .': '. $campaign->name."\n\n"
				.$item->emailAddress ." ". Yii::t('marketing','has clicked a link') .":\n". urldecode($url);

			if(isset($item->list)) {
				$action->associationType = 'X2List';
				$action->associationId = $item->list->id;
				$action->associationName = $item->list->name;
				$action->visibility = $item->list->visibility;
				$action->assignedTo = $item->list->assignedTo;
			} else { //should be never
				$action->visibility = 1;
				$action->assignedTo = 'Anyone';
			}

			X2Flow::trigger('NewsletterWebActivityTrigger',array(
				'item'=>$item,
				'campaign'=>$campaign,
				'url'=>$url,
			));
		}
		$action->save();

		if($item->contact)
			return $item->contact;

		return true;
	}

	public static function setKey($key) {
		setcookie('x2_key',$key,time()+31536000,dirname(Yii::app()->request->getScriptUrl()),Yii::app()->request->getServerName());	// set cookie for 1 year
	}
}
